﻿using Serialization.Script;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Sirian.Serialization;
using System.Reflection;
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework.Graphics;
using GlobalGameClasses;
using Serialization;
using Microsoft.Xna.Framework.Audio;

namespace SirianTestEnvironment
{
    
    
    /// <summary>
    ///This is a test class for ScriptReaderTest and is intended
    ///to contain all ScriptReaderTest Unit Tests
    ///</summary>
    [TestClass()]
    public class ScriptReaderTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext)
        {

            System.Windows.Forms.Form form = new System.Windows.Forms.Form();
            form.Visible = false;
            form.ShowInTaskbar = false;
            PresentationParameters param = new PresentationParameters();
            param.DeviceWindowHandle = form.Handle;
            param.IsFullScreen = false;
            GraphicsDevice device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, GraphicsProfile.HiDef, param);
            GlobalGameClasses.GlobalGameValues.Values.graphicsDevice = device;
            GlobalGameClasses.GlobalGameValues.Values.spriteBatch = new SpriteBatch(device);
            GlobalGameValues.Values.content.addTexture("smokeTexture", new Texture2D(device, 1, 1));
            GlobalGameValues.Values.content.addTexture("fireTexture", new Texture2D(device, 1, 1));
            GlobalGameValues.Values.content.addTexture("health", new Texture2D(device, 1, 1));
            GlobalGameValues.Values.content.addContent("aircraft_enemy1", null, new Texture2D(device, 1, 1));
            GlobalGameValues.Values.content.addContent("aircraft_enemy2", null, new Texture2D(device, 1, 1));
            GlobalGameValues.Values.content.addContent("aircraft_enemy3", null, new Texture2D(device, 1, 1));
            GlobalGameValues.Values.content.addContent("aircraft_enemy4", null, new Texture2D(device, 1, 1));
            GlobalGameValues.Values.content.addContent("aircraft_enemy5", null, new Texture2D(device, 1, 1)); 
            GlobalGameValues.Values.content.addContent("aircraft_boss", null, new Texture2D(device, 1, 1));

            GlobalGameClasses.GlobalGameValues.Values.content.addSong("music_boss", null);
        }
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        [ClassCleanup()]
        public static void MyClassCleanup()
        {
            GlobalGameValues.Values.achievementsUnlocked = new List<Achievement>();
            GlobalGameValues.Values.content = new ContentCollection();
            GlobalGameValues.Values.difficulty = null;
            GlobalGameValues.Values.errorWriter = null;
            GlobalGameValues.Values.gameTime = new GameTime();
            GlobalGameValues.Values.GlobalStrings = new StringContainer();
            GlobalGameValues.Values.graphicsDevice = null;
            GlobalGameValues.Values.score = new InterfaceComponents.HUDWrapper<int>(new List<InterfaceComponents.HUDComponent>());
            GlobalGameValues.Values.soundPlayer = null;
            GlobalGameValues.Values.spriteBatch = null;
            GlobalGameValues.Values.volume_Music = 0;
            GlobalGameValues.Values.volume_soundEffect = 0;
        }
        //
        #endregion


        /// <summary>
        ///A test for readLevelScript
        ///</summary>
        [TestMethod()]
        public void readLevelScriptTest()
        {
            string errorLogPath = System.IO.Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)) + "//logfile.log";
            clearLog(errorLogPath);
            string filePath = System.IO.Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) + "\\Out\\";
            ScriptReader target = new ScriptReader(filePath + "testScript1.scp");
            LogWriter logWriter = new LogWriter(errorLogPath);
            LevelScript levelScript = target.readLevelScript(logWriter);
            GameTime gameTime = new GameTime(new TimeSpan(int.MaxValue), new TimeSpan(int.MaxValue));
            levelScript.Update(gameTime);
            List<ScriptedEvent> events = levelScript.getPendingEvents();
            Assert.AreEqual(events.Count, 3);
            Assert.IsTrue(events[0] is Event_CreateEnemyWave);
            Assert.IsTrue(events[1] is Event_SetMusic);
            Assert.IsTrue(events[2] is Event_CreateBoss);
            Assert.IsTrue(events[0].eventTime == 129000);
            Assert.IsTrue(events[1].eventTime == 135000);
            Assert.IsTrue(events[2].eventTime == 140000);

            target = new ScriptReader(filePath + "testScript2.scp");
            levelScript = target.readLevelScript(logWriter);
            levelScript.Update(gameTime);
            events = levelScript.getPendingEvents();
            Assert.AreEqual(events.Count, 2);
            Assert.IsTrue(events[0] is Event_CreateEnemyWave);
            Assert.IsTrue(events[1] is Event_CreateEnemyWave);
            Assert.IsTrue(events[0].eventTime == 88000);
            Assert.IsTrue(events[1].eventTime == 95001);

            using (StreamReader sr = new StreamReader(errorLogPath))
            {
                string input = sr.ReadToEnd();
                string[] lines = input.Split('\n');
                Assert.AreEqual(lines.Length, 2);
                sr.Close();
            }

            clearLog(errorLogPath);

            target = new ScriptReader(filePath + "testScript3.scp");
            levelScript = target.readLevelScript(logWriter);
            levelScript.Update(gameTime);
            events = levelScript.getPendingEvents();
            Assert.AreEqual(events.Count, 0);

            using (StreamReader sr = new StreamReader(errorLogPath))
            {
                string input = sr.ReadToEnd();
                string[] lines = input.Split('\n');
                Assert.AreEqual(lines.Length, 6);
                sr.Close();
            }

            clearLog(errorLogPath);
        }

        private void clearLog(string logpath)
        {
            using (StreamWriter sw = new StreamWriter(logpath, false))
            {
                sw.Write("");
                sw.Close();
            }
        }
    }
}

